package com.prj.ufdm.web.security;

import java.util.Collection;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Service;
import com.prj.ufdm.web.enums.WebRetCodeEnum;

/**  
  * 鉴定用户是否有访问对应资源权限 
 * @author 胡义振  
 * @date 2018年3月23日  
*/
@Service
public class ScyDecisionImpl implements AccessDecisionManager {
	
	 private static final Logger logger = LoggerFactory.getLogger(ScyDecisionImpl.class);

	/**
	 * 判断访问的资源是否放行
	 * @param authentication   为  UserDetailsService 中 grantedAuthorities 权限
	 * @param object           包含客户端请求的requset信息
	 * @param configAttributes 为 FilterInvocationSecurityMetadataSource 的 getAttributes 返回结果
	 */
	@Override
	public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException {
		
		logger.debug("当前URL"+configAttributes);
		logger.debug("当前用户"+authentication.getPrincipal());
		logger.debug("当前用户所有权限"+authentication.getAuthorities());
		
		// 如果访问资源不需要任何权限则直接通过 
		if(null== configAttributes || configAttributes.size() <=0) {
            return;
        }
        String reqUrl = "";
        for(Iterator<ConfigAttribute> iter = configAttributes.iterator(); iter.hasNext(); ) {
        	reqUrl = iter.next().getAttribute();
            for(GrantedAuthority ga : authentication.getAuthorities()) {
                if(reqUrl.trim().equals(ga.getAuthority())) {
                	logger.debug("访问 URL("+reqUrl+") 在当前用户权限表中存在，允许访问");
                    return;
                }
            }
        }
        logger.debug("访问 URL("+reqUrl+") 在当前用户权限表中不存在，禁止访问");
		throw new AccessDeniedException(WebRetCodeEnum.RET_CODE_0801007.getCode());
	}

	
	/**
	 * supports(ConfigAttribute attribute)方法是用来判断AccessDecisionManager是否能够处理对应的ConfigAttribute的
	 */
	@Override
	public boolean supports(ConfigAttribute attribute) {
		return true;
	}

	/**
	 * supports(Class<?> clazz)方法用于判断配置的AccessDecisionManager是否支持对应的受保护对象类型。
	 */
	@Override
	public boolean supports(Class<?> clazz) {
		return true;
	}

}
